import 'dart:async';
import 'dart:isolate';

import 'package:meta/meta.dart';
import 'package:simulator/core/regisiter.dart';
import 'package:simulator/core/result.dart';
import 'package:simulator/utils/constant.dart';
import 'package:simulator/utils/log.dart';
import 'package:simulator/utils/rx_util.dart';
import 'package:simulator/utils/utils.dart';

///模块处理文件
///
///由n个寄存器的合集
///
abstract class Module {
  ///启动时传递的参数
  static late final Args _args;

  static void sendToHost(Result data) => _args.port.send(data);

  ///模块启动处理过程
  ///runZoned(() => null);
  ///模块运行除非异常，否则不会主动退出,全部由CPU线程控制
  static void loop(Result d) {
    _args = d.args!;
    runZonedGuarded(zonedStart, zoneValues: {}, (error, stack) {
      ///可以捕获到所有代码
      LogPrint.logErr('error--->$stack');
      Utils.getInstance().exitHook();
      Isolate.exit(
          _args.port, Result(type: ResultType.exception, exception: error));
    },
        zoneSpecification: ZoneSpecification(
          ///那么error-zone里发生的异常是不会跨越边界的
          handleUncaughtError: (self, parent, zone, error, stackTrace) {
            parent.print(self, 'handleUncaughtError-->$error');
          },
          errorCallback: (self, parent, zone, error, stackTrace) {
            parent.print(self, 'errorCallback-->$error');
            return AsyncError(error, stackTrace);
          },
          print: (self, parent, zone, msg) {
            parent.print(self, '[Module]-->$msg');
          },
        ));
  }

  static void zonedStart() async {
    Zone.current[''];
    //_args.port.send('message');
    final List<Module> modules = _args.module ?? [];
    ReceivePort receivePort = ReceivePort();
    receivePort.listen((e) {
      assert(e is Result, 'Iso must has Result data type: $e');
      e as Result;
      switch (e.type) {
        case ResultType.regisiter:

          ///接收寄存器变化的消息,并同步到本地模块,通过监听寄存器地址的消息
          Rx.getInstance().push(e.update!.addr.toString(), data: e.update);
          break;

        case ResultType.exit:
          Isolate.exit(_args.port, const Result(type: ResultType.exit));
        case ResultType.args:
        case ResultType.interrupt:
        case ResultType.exception:
        case ResultType.unkonw:
          LogPrint.logWarn('get Host unkonw cmd $e');
      }
    }, onDone: () {
      LogPrint.logErr('root listen Done');
    }, onError: (e) {
      LogPrint.logErr('root get error listen: $e');
    });

    ///开始监听寄存器变化
    Rx.getInstance().subscribe(signRegisiter, (data) {
      sendToHost(Result(type: ResultType.regisiter, update: data));
    });
    Utils.getInstance()
        .addShutdownHook(() => Rx.getInstance().unSubscribe(signRegisiter));

    ///发送一下端口
    sendToHost(
        Result(type: ResultType.args, args: Args(port: receivePort.sendPort)));
    Utils.getInstance().addShutdownHook(receivePort.close);
    for (var element in modules) {
      Utils.getInstance().addShutdownHook(element.exit);
      element.init();
      element.exec();
    }
    while (modules.isNotEmpty) {
      ///判断各个模块运行状态,即时通知主模块状态
      modules.removeWhere((element) {
        if (!element.state) return true;

        ///发送通知移除了
        return false;
      });
      await Future.delayed(Duration.zero);
    }
    LogPrint.logInfo('exit loop');
    Utils.getInstance().exitHook();
    Isolate.exit(_args.port, const Result(type: ResultType.exit));
  }

  Module(
      {required this.name,
      required this.state,
      required this.sync_,
      required this.registers});

  ///寄存器合集
  ///模块这边不再修改这个值,当前值都存在CPU线程
  final List<Regisiter> registers;

  ///模块运行状态,模块不能被debug
  bool state;

  ///是否在CPU线程中处理,
  ///1. true表示在本线程中处理,重要的module组放在CPU线程
  bool sync_;

  String name;

  ///模块初始化,先添加所有寄存器再监听
  @mustCallSuper
  void init() {
    for (var element in registers) {
      Rx.getInstance().subscribe(element.addr.toString(), callback);
    }
    LogPrint.logDbg('$name init');
  }

  void callback(data);

  ///协程模块自己处理
  ///
  ///一定要在死循环中调用await Future.delayed(const Duration(seconds: 1));
  ///让出CPU使用权
  Future<bool> exec();

  ///退出
  @mustCallSuper
  void exit() {
    for (var element in registers) {
      Rx.getInstance().unSubscribe(element.addr.toString());
    }
    LogPrint.logDbg('$name exit');
  }

  @override
  String toString() {
    return name;
  }
}

///GPIO 模块
class GpioModule extends Module {
  GpioModule(
      {required super.name,
      super.sync_ = true,
      super.state = true,
      super.registers = const []});

  @override
  Future<bool> exec() async {
    int i = 0;
    state = true;
    while (state) {
      await Future.delayed(const Duration(seconds: 1));
      print('exec:${i++}');
      if (i == 5) state = false;
    }
    return false;
  }

  @override
  void callback(data) {
    data as RegisiterUpdate;
    print('callback:$data');
  }
}

class ExamModule extends Module {
  ExamModule(
      {required super.name,
      super.sync_ = true,
      super.state = true,
      super.registers = const []});
  @override
  Future<bool> exec() async {
    state = true;
    while (state) {
      await Future.delayed(const Duration(seconds: 1));
      print('ExamModule exec');
    }
    return true;
  }

  @override
  void callback(data) {
    data as RegisiterUpdate;
    print('ExamModule callback:$data');
  }
}
